/**
 * 
 */
package org.crystal.jqweb.config;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.crystal.jqweb.config.*;
/**
 * @author Crystal
 * 
 */
public class ActionConfig {
	private final Log log = LogFactory.getLog(getClass());
	private static ActionConfig instance = null;
	private Map actions;
	private String xmlFileName;

	public static synchronized ActionConfig getInstance() {
		if (instance == null) {
			instance = new ActionConfig();
			instance.log.debug("getInstance()" +" new ActionConfig instance");
		}
		return instance;
	}

	public static synchronized ActionConfig getInstance(String xmlFileName) {
		if (instance == null) {
			instance = new ActionConfig(xmlFileName);
			instance.log.debug("getInstance()" +" new ActionConfig instance(xmlFileName)");
		}
		return instance;
	}

	public Boolean isXmlExists(String xmlFileName) {
		this.xmlFileName = xmlFileName;

		File file = new File(this.xmlFileName);
		if (!file.exists()) {
			log.info("isXmlExists() " +this.xmlFileName + " (file name) doesn't found!");
			return false;
		}
		log.info("isXmlExists() " +this.xmlFileName + " (file name) is found!");
		return true;

	}

	ActionConfig() {
		actions = new HashMap();
		//xmlFileName = "D:\\SoftWare\\MyEclipse\\workspace\\JqWeb\\src\\jqweb-config.xml";
		buildXmlConfig();
	}

	ActionConfig(String xmlFileName) {
		actions = new HashMap();
		this.xmlFileName = xmlFileName;
		buildXmlConfig();
	}

	private void buildXmlConfig() {
		log.info("buildXmlConfig() ");
		try {
			if (isXmlExists(xmlFileName)) {
				DocumentBuilderFactory factory = DocumentBuilderFactory
						.newInstance();
				DocumentBuilder builder = factory.newDocumentBuilder();
				Document doc = builder.parse(xmlFileName);
				TransformerFactory tranFactory = TransformerFactory.newInstance();
				Transformer aTransformer = tranFactory.newTransformer();
	
				//load actions
				NodeList list = doc.getElementsByTagName("jxaction");
				
				for (int i = 0; i < list.getLength(); i++) {
					// Get element
					Element element = (Element) list.item(i);
					ActionElement ae = new ActionElement();
					ae.setName( element.getAttribute("name"));
					ae.setAction( element.getAttribute("action"));
					ae.setMethod( element.getAttribute("method"));
					ae.setActionCls( element.getAttribute("class"));
					log.info("buildXmlConfig() ********************action "+ae.getAction()+"********************************");
					log.info("buildXmlConfig() name:"+ae.getName()+", action:"+ae.getAction()+", method:"+ae.getMethod()+", class:"+ae.getActionCls());
		
					NodeList listChild = element.getElementsByTagName("toview");
					
					for (int j = 0; j < listChild.getLength(); j++) {
						
						Element cldElement = ((Element) listChild.item(j));
						ToView tv = new ToView();
						tv.setName(cldElement.getAttribute("name"));
						tv.setType(cldElement.getAttribute("type"));
						tv.setScope(cldElement.getAttribute("scope"));
						tv.setToView(cldElement.getTextContent());
						ae.getToView().put(tv.getName(), tv);
						
						log.info("buildXmlConfig() name:"+tv.getName()+", toView:"+tv.getToView()+", type:"+tv.getType()+", scope:"+tv.getScope());
						
					}
					log.info("buildXmlConfig() ********************end action "+ae.getAction()+"********************************");
					actions.put(element.getAttribute("action"), ae);

				}
				
				//sub Module load from config files
				NodeList jqwebModuleList=doc.getElementsByTagName("jqwebModule");
				for (int i = 0; i < jqwebModuleList.getLength(); i++) {
					String jqwebModuleXmlFile=((Element) jqwebModuleList.item(i)).getAttribute("resource");
					log.info("buildXmlConfig() ********************load... module xml file: "+jqwebModuleXmlFile+"****************");
					this.buildXmlModuleConfig(ConfigFile.getInstance().getWebRoot()+jqwebModuleXmlFile);
					log.info("buildXmlConfig() ********************loaded module xml file: "+jqwebModuleXmlFile+"*****************");
				}
				
			}
		} catch (Exception e) {
			e.getMessage();
		}
	}
	
	private void buildXmlModuleConfig(String xmlFileName) {
		log.info("buildXmlModuleConfig() ");
		try {
			if (isXmlExists(xmlFileName)) {
				DocumentBuilderFactory factory = DocumentBuilderFactory
						.newInstance();
				DocumentBuilder builder = factory.newDocumentBuilder();
				Document doc = builder.parse(xmlFileName);
				TransformerFactory tranFactory = TransformerFactory.newInstance();
				Transformer aTransformer = tranFactory.newTransformer();

				NodeList list = doc.getElementsByTagName("jxaction");
				
				for (int i = 0; i < list.getLength(); i++) {
					// Get element
					Element element = (Element) list.item(i);
					ActionElement ae = new ActionElement();
					ae.setName( element.getAttribute("name"));
					ae.setAction( element.getAttribute("action"));
					ae.setMethod( element.getAttribute("method"));
					ae.setActionCls( element.getAttribute("class"));
					log.info("buildXmlModuleConfig() ********************action "+ae.getAction()+"********************************");
					log.info("buildXmlModuleConfig() name:"+ae.getName()+", action:"+ae.getAction()+", method:"+ae.getMethod()+", class:"+ae.getActionCls());
		
					NodeList listChild = element.getElementsByTagName("toview");
					
					for (int j = 0; j < listChild.getLength(); j++) {
						
						Element cldElement = ((Element) listChild.item(j));
						ToView tv = new ToView();
						tv.setName(cldElement.getAttribute("name"));
						tv.setType(cldElement.getAttribute("type"));
						tv.setScope(cldElement.getAttribute("scope"));
						tv.setToView(cldElement.getTextContent());
						ae.getToView().put(tv.getName(), tv);
						
						log.info("buildXmlModuleConfig() name:"+tv.getName()+", toView:"+tv.getToView()+", type:"+tv.getType()+", scope:"+tv.getScope());
						
					}
					log.info("buildXmlModuleConfig() ********************end action "+ae.getAction()+"********************************");
					actions.put(element.getAttribute("action"), ae);

				}
			}
		} catch (Exception e) {
			e.getMessage();
		}
	}
	
	public  Object getAction(String action){
		return actions.get(action);
	}
	public  Object getToView(String action,String viewName){
		return ((ActionElement)actions.get(action)).getToView().get(viewName);
	}
}
